{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Interpretability Result in FedMA\n",
    "\n",
    "In this jupyter notebook, we provide the code to reproduce the \"Interpretability\" experiments (see Section 3 for more details) in FedMA paper."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pickle\n",
    "import copy\n",
    "from sklearn.preprocessing import normalize\n",
    "from utils import *\n",
    "\n",
    "from matching.pfnm import layer_wise_group_descent\n",
    "from matching.pfnm import layer_wise_group_descent_comm, layer_wise_group_descent_comm2, layer_wise_group_descent_comm3\n",
    "from matching.pfnm import block_patching, patch_weights\n",
    "from matching.gaus_marginal_matching import match_local_atoms\n",
    "\n",
    "import logging\n",
    "\n",
    "from model import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "dummy_cnn = ModerateCNN()\n",
    "layer_type = []\n",
    "for (k, v) in dummy_cnn.state_dict().items():\n",
    "    layer_type.append(k)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "logging.basicConfig()\n",
    "logger = logging.getLogger()\n",
    "logger.setLevel(logging.INFO)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# we load retrained weights here:\n",
    "with open(\"./first_round_retraining_weights\", \"rb\") as out_file:\n",
    "    batch_weights = pickle.load(out_file)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "n_layers = int(len(batch_weights[0]) / 2)\n",
    "num_workers = len(batch_weights)\n",
    "\n",
    "matching_shapes_old = []\n",
    "matching_shapes_new = []\n",
    "\n",
    "first_fc_index = None\n",
    "gamma = 5.0\n",
    "sigma = 1.0\n",
    "sigma0 = 1.0\n",
    "n_classes = 10\n",
    "it=5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Files already downloaded and verified\n",
      "Files already downloaded and verified\n"
     ]
    }
   ],
   "source": [
    "args_dataset = \"cifar10\"\n",
    "args_datadir = \"./data/cifar10\"\n",
    "args_batch_size = 64\n",
    "\n",
    "train_dl_global, test_dl_global = get_dataloader(args_dataset, args_datadir, args_batch_size, 32)\n",
    "matching_shapes = []"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def ___trans_next_conv_layer_forward(layer_weight, next_layer_shape):\n",
    "    reshaped = layer_weight.reshape(next_layer_shape).transpose((1, 0, 2, 3)).reshape((next_layer_shape[1], -1))\n",
    "    return reshaped\n",
    "\n",
    "def ___trans_next_conv_layer_backward(layer_weight, next_layer_shape):\n",
    "    reconstructed_next_layer_shape = (next_layer_shape[1], next_layer_shape[0], next_layer_shape[2], next_layer_shape[3])\n",
    "    reshaped = layer_weight.reshape(reconstructed_next_layer_shape).transpose(1, 0, 2, 3).reshape(next_layer_shape[0], -1)\n",
    "    return reshaped"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(32, 27)\n",
      "(70, 288)\n",
      "Are those weights equal: True\n"
     ]
    }
   ],
   "source": [
    "import copy\n",
    "\n",
    "test_weight = copy.deepcopy(batch_weights[0][2])\n",
    "\n",
    "print(batch_weights[0][0].shape)\n",
    "print(test_weight.shape)\n",
    "\n",
    "next_layer_shape = (70, 32, 3, 3)\n",
    "\n",
    "reshaped_weight = ___trans_next_conv_layer_forward(test_weight, next_layer_shape)\n",
    "reshaped_back_weight = ___trans_next_conv_layer_backward(reshaped_weight, next_layer_shape)\n",
    "\n",
    "print(\"Are those weights equal: {}\".format(np.array_equal(test_weight, reshaped_back_weight)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def compute_full_cnn_accuracy(models, weights, train_dl, test_dl, n_classes, args_model, args_dataset):\n",
    "    \"\"\"Note that we only handle the FC weights for now\"\"\"\n",
    "    # we need to figure out the FC dims first\n",
    "\n",
    "    #LeNetContainer\n",
    "    # def __init__(self, num_filters, kernel_size, input_dim, hidden_dims, output_dim=10)\n",
    "\n",
    "    # this should be safe to be hard-coded since most of the modern image classification dataset are in RGB format\n",
    "    #args_n_nets = len(models)\n",
    "\n",
    "    if args_model == \"lenet\":\n",
    "        num_filters = [weights[0].shape[0], weights[2].shape[0]]\n",
    "        kernel_size = 5\n",
    "        input_dim = weights[4].shape[0]\n",
    "        hidden_dims = [weights[4].shape[1]]\n",
    "\n",
    "        output_dim = weights[-1].shape[0]\n",
    "\n",
    "        logger.info(\"Num filters: {}, Input dim: {}, hidden_dims: {}, output_dim: {}\".format(num_filters, input_dim, hidden_dims, output_dim))\n",
    "\n",
    "        matched_cnn = LeNetContainer(\n",
    "                                    num_filters=num_filters,\n",
    "                                    kernel_size=kernel_size,\n",
    "                                    input_dim=input_dim,\n",
    "                                    hidden_dims=hidden_dims,\n",
    "                                    output_dim=output_dim)\n",
    "    elif args_model == \"vgg\":\n",
    "        matched_shapes = [w.shape for w in weights]\n",
    "        matched_cnn = matched_vgg11(matched_shapes=matched_shapes)\n",
    "    elif args_model == \"simple-cnn\":\n",
    "        # input_channel, num_filters, kernel_size, input_dim, hidden_dims, output_dim=10):\n",
    "        # [(9, 75), (9,), (19, 225), (19,), (475, 123), (123,), (123, 87), (87,), (87, 10), (10,)]\n",
    "        if args_dataset in (\"cifar10\", \"cinic10\"):\n",
    "            input_channel = 3\n",
    "        elif args_dataset == \"mnist\":\n",
    "            input_channel = 1\n",
    "        num_filters = [weights[0].shape[0], weights[2].shape[0]]\n",
    "        input_dim = weights[4].shape[0]\n",
    "        hidden_dims = [weights[4].shape[1], weights[6].shape[1]]\n",
    "        matched_cnn = SimpleCNNContainer(input_channel=input_channel, \n",
    "                                        num_filters=num_filters, \n",
    "                                        kernel_size=5, \n",
    "                                        input_dim=input_dim, \n",
    "                                        hidden_dims=hidden_dims, \n",
    "                                        output_dim=10)\n",
    "    elif args_model == \"moderate-cnn\":\n",
    "        #[(35, 27), (35,), (68, 315), (68,), (132, 612), (132,), (132, 1188), (132,), \n",
    "        #(260, 1188), (260,), (260, 2340), (260,), \n",
    "        #(4160, 1025), (1025,), (1025, 515), (515,), (515, 10), (10,)]\n",
    "        num_filters = [weights[0].shape[0], weights[2].shape[0], weights[4].shape[0], weights[6].shape[0], weights[8].shape[0], weights[10].shape[0]]\n",
    "        input_dim = weights[12].shape[0]\n",
    "        hidden_dims = [weights[12].shape[1], weights[14].shape[1]]\n",
    "        if args_dataset in (\"cifar10\", \"cinic10\"):\n",
    "            matched_cnn = ModerateCNNContainer(3,\n",
    "                                                num_filters, \n",
    "                                                kernel_size=3, \n",
    "                                                input_dim=input_dim, \n",
    "                                                hidden_dims=hidden_dims, \n",
    "                                                output_dim=10)\n",
    "        elif args_dataset == \"mnist\":\n",
    "            matched_cnn = ModerateCNNContainer(1,\n",
    "                                                num_filters, \n",
    "                                                kernel_size=3, \n",
    "                                                input_dim=input_dim, \n",
    "                                                hidden_dims=hidden_dims, \n",
    "                                                output_dim=10)\n",
    "\n",
    "    #logger.info(\"Keys of layers of convblock ...\")\n",
    "    new_state_dict = {}\n",
    "    model_counter = 0\n",
    "    # handle the conv layers part which is not changing\n",
    "    for param_idx, (key_name, param) in enumerate(matched_cnn.state_dict().items()):\n",
    "        #print(\"&\"*30)\n",
    "        #print(\"Key: {}, Weight Shape: {}, Matched weight shape: {}\".format(key_name, param.size(), weights[param_idx].shape))\n",
    "        #print(\"&\"*30)\n",
    "        if \"conv\" in key_name or \"features\" in key_name:\n",
    "            if \"weight\" in key_name:\n",
    "                temp_dict = {key_name: torch.from_numpy(weights[param_idx].reshape(param.size()))}\n",
    "            elif \"bias\" in key_name:\n",
    "                temp_dict = {key_name: torch.from_numpy(weights[param_idx])}\n",
    "        elif \"fc\" in key_name or \"classifier\" in key_name:\n",
    "            if \"weight\" in key_name:\n",
    "                temp_dict = {key_name: torch.from_numpy(weights[param_idx].T)}\n",
    "            elif \"bias\" in key_name:\n",
    "                temp_dict = {key_name: torch.from_numpy(weights[param_idx])}\n",
    "\n",
    "        new_state_dict.update(temp_dict)\n",
    "    matched_cnn.load_state_dict(new_state_dict)\n",
    "\n",
    "    matched_cnn.eval()\n",
    "    ##    \n",
    "    \n",
    "    correct, total = 0, 0\n",
    "    for batch_idx, (x, target) in enumerate(test_dl):\n",
    "        out_k = matched_cnn(x)\n",
    "        _, pred_label = torch.max(out_k, 1)\n",
    "        total += x.data.size()[0]\n",
    "        correct += (pred_label == target.data).sum().item()\n",
    "        \n",
    "    logger.info(\"Accuracy for Neural Matching correct: {}, total: {}\".format(correct, total))\n",
    "    \n",
    "\n",
    "class ModerateCNNContainerConvBlocks(nn.Module):\n",
    "    def __init__(self, num_filters, output_dim=10):\n",
    "        super(ModerateCNNContainerConvBlocks, self).__init__()\n",
    "\n",
    "        self.conv_layer = nn.Sequential(\n",
    "            # Conv Layer block 1\n",
    "            nn.Conv2d(in_channels=3, out_channels=num_filters[0], kernel_size=3, padding=1),\n",
    "            nn.ReLU(inplace=True),\n",
    "            #nn.Conv2d(in_channels=num_filters[0], out_channels=num_filters[1], kernel_size=3, padding=1),\n",
    "            #nn.ReLU(inplace=True),\n",
    "        )\n",
    "\n",
    "    def forward(self, x):\n",
    "        x = self.conv_layer(x)\n",
    "        return x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:root:Handling layer: 1\n",
      "INFO:root:init_channel_kernel_dims: [27, 288, 630, 1197, 1206, 2367, 1025, 516, 10]\n",
      "INFO:root:Layer index: 1, init_num_kernel: 32\n",
      "INFO:root:weights bias: (32, 28)\n",
      "INFO:root:sigma_inv_prior shape: (28,)\n",
      "INFO:root:mean_prior shape: (28,)\n",
      "INFO:root:Number of global neurons is 34, gamma 5.000000\n",
      "INFO:root:***************Shape of global weights after match: (34, 28) ******************\n",
      "INFO:root:Branch A, Layer index: 1, Global weights out shapes: [(34, 27), (34,)]\n",
      "INFO:root:global inv sigma out shape: [(34, 27), (34,)]\n"
     ]
    }
   ],
   "source": [
    "layer_index = 1\n",
    "model_meta_data = [(32, 3, 3, 3), (32, ), (70, 32, 3, 3), (70,)]\n",
    "logger.info(\"Handling layer: {}\".format(layer_index))\n",
    "layer_hungarian_weights_old, assignment_old, L_next_old = layer_wise_group_descent_comm(\n",
    "     batch_weights=batch_weights, \n",
    "     layer_index=layer_index,\n",
    "     sigma0_layers=sigma0, \n",
    "     sigma_layers=sigma, \n",
    "     batch_frequencies=None, \n",
    "     it=it, \n",
    "     gamma_layers=gamma, \n",
    "     model_meta_data=model_meta_data,\n",
    "     model_layer_type=layer_type,\n",
    "     n_layers=n_layers,\n",
    "     matching_shapes=matching_shapes,\n",
    "     args=None\n",
    "     )\n",
    "matching_shapes_old.append(L_next_old)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:root:Handling layer: 1\n",
      "INFO:root:init_channel_kernel_dims: [27, 288, 630, 1197, 1206, 2367, 1025, 516, 10]\n",
      "INFO:root:Layer index: 1, init_num_kernel: 32\n",
      "INFO:root:weights bias: (32, 28)\n",
      "INFO:root:sigma_inv_prior shape: (28,)\n",
      "INFO:root:mean_prior shape: (28,)\n",
      "INFO:root:Branch A, Layer index: 1, Global weights out shapes: [(34, 27), (34,)]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Init mu0 estimate mean is -0.000121\n",
      "Init Sigma mean estimate is 0.015700; sigma0 is 0.015051; mu0 is -0.000121\n",
      "Init objective (without prior) is 4763.361315; number of global atoms is 32\n",
      "Sigma mean estimate is 0.015413; sigma0 is 0.015068; mu0 is -0.000405\n",
      "Matching iteration 0\n",
      "Objective (without prior) at iteration 0 is 5121.931010; number of global atoms is 34\n",
      "Sigma mean estimate is 0.015413; sigma0 is 0.015068; mu0 is -0.000405\n",
      "Matching iteration 1\n",
      "Objective (without prior) at iteration 1 is 5121.931010; number of global atoms is 34\n",
      "Sigma mean estimate is 0.015413; sigma0 is 0.015068; mu0 is -0.000405\n",
      "Matching iteration 2\n",
      "Objective (without prior) at iteration 2 is 5121.931010; number of global atoms is 34\n",
      "Sigma mean estimate is 0.015413; sigma0 is 0.015068; mu0 is -0.000405\n",
      "Matching iteration 3\n",
      "Objective (without prior) at iteration 3 is 5121.931010; number of global atoms is 34\n",
      "Sigma mean estimate is 0.015413; sigma0 is 0.015068; mu0 is -0.000405\n",
      "Matching iteration 4\n",
      "Objective (without prior) at iteration 4 is 5121.931010; number of global atoms is 34\n",
      "Number of global atoms is 34, gamma 5.000000\n"
     ]
    }
   ],
   "source": [
    "layer_index = 1\n",
    "model_meta_data = [(32, 3, 3, 3), (32, ), (70, 32, 3, 3), (70,)]\n",
    "logger.info(\"Handling layer: {}\".format(layer_index))\n",
    "layer_hungarian_weights_new, assignment_new, L_next_new = layer_wise_group_descent_comm3(\n",
    "     batch_weights=batch_weights, \n",
    "     layer_index=layer_index,\n",
    "     sigma0_layers=sigma0, \n",
    "     sigma_layers=sigma, \n",
    "     batch_frequencies=None, \n",
    "     it=it, \n",
    "     gamma_layers=gamma, \n",
    "     model_meta_data=model_meta_data,\n",
    "     model_layer_type=layer_type,\n",
    "     n_layers=n_layers,\n",
    "     matching_shapes=matching_shapes,\n",
    "     args=None\n",
    "     )\n",
    "matching_shapes_new.append(L_next_new)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visualizing the Matched Filters here:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:root:Assignment for batch 1: [0, 1, 2, 3, 28, 4, 5, 6, 7, 8, 9, 30, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 31, 29]\n",
      "INFO:root:\n",
      "INFO:root:Assignment for batch 2: [25, 6, 23, 22, 13, 12, 3, 2, 20, 7, 26, 32, 27, 17, 28, 24, 14, 29, 11, 8, 16, 21, 1, 0, 15, 19, 18, 10, 5, 9, 33, 4]\n"
     ]
    }
   ],
   "source": [
    "logger.info(\"Assignment for batch 1: {}\".format(assignment_new[0]))\n",
    "logger.info(\"\")\n",
    "logger.info(\"Assignment for batch 2: {}\".format(assignment_new[1]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:root:0\n",
      "INFO:root:23\n"
     ]
    }
   ],
   "source": [
    "# it seems the first filter of batch 1 and the 24-rd filter of batch 2 is matched\n",
    "logger.info(assignment_new[0].index(0))\n",
    "logger.info(assignment_new[1].index(0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "\n",
    "import matplotlib\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(3, 3, 3)\n"
     ]
    }
   ],
   "source": [
    "filter1_batch1 = batch_weights[0][0][0].reshape(3, 3, 3)\n",
    "filter24_batch2 = batch_weights[1][0][23].reshape(3, 3, 3)\n",
    "print(filter1_batch1.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "dumm_conv_block1 = ModerateCNNContainerConvBlocks([32])\n",
    "dumm_conv_block2 = ModerateCNNContainerConvBlocks([32])\n",
    "dumm_conv_block_avg = ModerateCNNContainerConvBlocks([32])\n",
    "dumm_conv_block_matched = ModerateCNNContainerConvBlocks([34])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<All keys matched successfully>"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "new_state_dict = {}\n",
    "# handle the conv layers part which is not changing\n",
    "for param_idx, (key_name, param) in enumerate(dumm_conv_block1.state_dict().items()):\n",
    "    if \"conv\" in key_name or \"features\" in key_name:\n",
    "        if \"weight\" in key_name:\n",
    "            temp_dict = {key_name: torch.from_numpy(batch_weights[0][param_idx].reshape(param.size()))}\n",
    "        elif \"bias\" in key_name:\n",
    "            temp_dict = {key_name: torch.from_numpy(batch_weights[0][param_idx])}\n",
    "    new_state_dict.update(temp_dict)\n",
    "dumm_conv_block1.load_state_dict(new_state_dict)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<All keys matched successfully>"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "new_state_dict = {}\n",
    "# handle the conv layers part which is not changing\n",
    "for param_idx, (key_name, param) in enumerate(dumm_conv_block2.state_dict().items()):\n",
    "    if \"conv\" in key_name or \"features\" in key_name:\n",
    "        if \"weight\" in key_name:\n",
    "            temp_dict = {key_name: torch.from_numpy(batch_weights[1][param_idx].reshape(param.size()))}\n",
    "        elif \"bias\" in key_name:\n",
    "            temp_dict = {key_name: torch.from_numpy(batch_weights[1][param_idx])}\n",
    "    new_state_dict.update(temp_dict)\n",
    "dumm_conv_block2.load_state_dict(new_state_dict)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(34, 27)\n",
      "(34,)\n",
      "(70, 288)\n"
     ]
    }
   ],
   "source": [
    "# our plan is to construct new hungarian weights:\n",
    "manual_hungarian_weights_new = [np.zeros(lhw.shape).astype(np.float32) for lhw in layer_hungarian_weights_new]\n",
    "for mhw in manual_hungarian_weights_new:\n",
    "    print(mhw.shape)\n",
    "print(batch_weights[0][2].shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "# we now assign value to manual hungarian weights:\n",
    "_ori_shape = (70, 32, 3, 3)\n",
    "_matched_shape = (70, L_next_new, 3, 3)\n",
    "for global_neural_index in range(L_next_new):\n",
    "    if (global_neural_index in assignment_new[0]) and (global_neural_index in assignment_new[1]):\n",
    "        # we need to handle three associated pieces\n",
    "        for idx, mhw in enumerate(manual_hungarian_weights_new):\n",
    "            if len(mhw.shape) == 2:\n",
    "                candidate1 = batch_weights[0][idx][assignment_new[0].index(global_neural_index),:]\n",
    "                candidate2 = batch_weights[1][idx][assignment_new[1].index(global_neural_index),:]\n",
    "                manual_hungarian_weights_new[idx][global_neural_index, :] = 0.5*(candidate1+candidate2)\n",
    "            elif len(mhw.shape) == 1:\n",
    "                manual_hungarian_weights_new[idx][global_neural_index] = 0.5*(batch_weights[0][idx][assignment_new[0].index(global_neural_index)]+batch_weights[1][idx][assignment_new[1].index(global_neural_index)])\n",
    "    else:\n",
    "        if global_neural_index in assignment_new[0]:\n",
    "            for idx, mhw in enumerate(manual_hungarian_weights_new):\n",
    "                if len(mhw.shape) == 2:\n",
    "                    manual_hungarian_weights_new[idx][global_neural_index, :] = batch_weights[0][idx][assignment_new[0].index(global_neural_index),:]\n",
    "                elif len(mhw.shape) == 1:\n",
    "                    manual_hungarian_weights_new[idx][global_neural_index] = batch_weights[0][idx][assignment_new[0].index(global_neural_index)]\n",
    "        else:\n",
    "            for idx, mhw in enumerate(manual_hungarian_weights_new):\n",
    "                if len(mhw.shape) == 2:\n",
    "                    manual_hungarian_weights_new[idx][global_neural_index, :] = batch_weights[1][idx][assignment_new[1].index(global_neural_index),:]\n",
    "                elif len(mhw.shape) == 1:\n",
    "                    manual_hungarian_weights_new[idx][global_neural_index] = batch_weights[1][idx][assignment_new[1].index(global_neural_index)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<All keys matched successfully>"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "new_state_dict = {}\n",
    "# handle the conv layers part which is not changing\n",
    "for param_idx, (key_name, param) in enumerate(dumm_conv_block_matched.state_dict().items()):\n",
    "    if \"conv\" in key_name or \"features\" in key_name:\n",
    "        if \"weight\" in key_name:\n",
    "            #temp_dict = {key_name: torch.from_numpy(layer_hungarian_weights_new[param_idx].reshape(param.size()))}\n",
    "            temp_dict = {key_name: torch.from_numpy(manual_hungarian_weights_new[param_idx].reshape(param.size()))}\n",
    "        elif \"bias\" in key_name:\n",
    "            #temp_dict = {key_name: torch.from_numpy(layer_hungarian_weights_new[param_idx])}\n",
    "            temp_dict = {key_name: torch.from_numpy(manual_hungarian_weights_new[param_idx])}\n",
    "    new_state_dict.update(temp_dict)\n",
    "dumm_conv_block_matched.load_state_dict(new_state_dict)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<All keys matched successfully>"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "new_state_dict = {}\n",
    "# handle the conv layers part which is not changing\n",
    "for param_idx, (key_name, param) in enumerate(dumm_conv_block_avg.state_dict().items()):\n",
    "    if \"conv\" in key_name or \"features\" in key_name:\n",
    "        if \"weight\" in key_name:\n",
    "            #temp_dict = {key_name: torch.from_numpy(((0.2*batch_weights[0][param_idx]+0.8*batch_weights[1][param_idx])).reshape(param.size()))}\n",
    "            temp_dict = {key_name: torch.from_numpy(((0.5*batch_weights[0][param_idx]+0.5*batch_weights[1][param_idx])).reshape(param.size()))}\n",
    "        elif \"bias\" in key_name:\n",
    "            #temp_dict = {key_name: torch.from_numpy((0.2*batch_weights[0][param_idx]+0.8*batch_weights[1][param_idx]))}\n",
    "            temp_dict = {key_name: torch.from_numpy((0.5*batch_weights[0][param_idx]+0.5*batch_weights[1][param_idx]))}\n",
    "    new_state_dict.update(temp_dict)\n",
    "dumm_conv_block_avg.load_state_dict(new_state_dict)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Files already downloaded and verified\n"
     ]
    }
   ],
   "source": [
    "from torchvision import datasets, transforms\n",
    "\n",
    "trainset_cifar10 = datasets.CIFAR10(root='./data/cifar10', train=True,\n",
    "                                        download=True, transform=transforms.Compose([\n",
    "               transforms.ToTensor(),\n",
    "               transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))\n",
    "           ]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "\n",
    "import matplotlib\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [],
   "source": [
    "#imgplot = plt.imshow(trainset_cifar10.data[1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [],
   "source": [
    "transform_train = transforms.Compose([\n",
    "    transforms.ToPILImage(),\n",
    "    transforms.ToTensor(),\n",
    "    ])\n",
    "# load training and test set here:\n",
    "train_loader = torch.utils.data.DataLoader(trainset_cifar10, batch_size=1,\n",
    "                                          shuffle=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [],
   "source": [
    "for batch_idx, (train_image_batch, train_label_batch) in enumerate(train_loader):\n",
    "    if batch_idx == 1:\n",
    "        trial_example = train_image_batch\n",
    "    #print(train_image_batch.size())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [],
   "source": [
    "output_batch1 = dumm_conv_block1(trial_example)\n",
    "output_batch2 = dumm_conv_block2(trial_example)\n",
    "output_avg = dumm_conv_block_avg(trial_example)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [],
   "source": [
    "sliced_output_batch1 = output_batch1[0][0].detach().numpy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5,1,'FedAvg, Filter 0')"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1080x216 with 5 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = plt.figure(figsize=(15, 3))\n",
    "plt.subplot(151)\n",
    "plt.imshow(trainset_cifar10.data[1])\n",
    "plt.title(\"Raw Input2\", fontsize=15)\n",
    "plt.subplot(153)\n",
    "plt.imshow(sliced_output_batch1)\n",
    "plt.title(\"Client1, Filter 0\", fontsize=15)\n",
    "plt.subplot(154)\n",
    "sliced_output_batch2 = output_batch2[0][23].detach().numpy()\n",
    "plt.imshow(sliced_output_batch2)\n",
    "plt.title(\"Client2, Filter 23\", fontsize=15)\n",
    "plt.subplot(152)\n",
    "output_batch_matched = dumm_conv_block_matched(trial_example)\n",
    "output_batch_matched = output_batch_matched[0][0].detach().numpy()\n",
    "plt.imshow(output_batch_matched)\n",
    "#plt.title(\"Client1, Filter 0\", fontsize=15)\n",
    "plt.title(\"FedMA filter0\", fontsize=15)\n",
    "plt.subplot(155)\n",
    "output_batch_avg = dumm_conv_block_avg(trial_example)\n",
    "output_batch_avg = output_batch_avg[0][0].detach().numpy()\n",
    "plt.imshow(output_batch_avg)\n",
    "plt.title(\"FedAvg, Filter 0\", fontsize=15)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [],
   "source": [
    "for batch_idx, (train_image_batch, train_label_batch) in enumerate(train_loader):\n",
    "    if batch_idx == 7:\n",
    "        trial_example = train_image_batch\n",
    "    #print(train_image_batch.size())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [],
   "source": [
    "output_batch1 = dumm_conv_block1(trial_example)\n",
    "output_batch2 = dumm_conv_block2(trial_example)\n",
    "output_avg = dumm_conv_block_avg(trial_example)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [],
   "source": [
    "sliced_output_batch1 = output_batch1[0][0].detach().numpy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5,1,'FedAvg, Filter 0')"
      ]
     },
     "execution_count": 79,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1080x216 with 5 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = plt.figure(figsize=(15, 3))\n",
    "plt.subplot(151)\n",
    "plt.imshow(trainset_cifar10.data[7])\n",
    "plt.title(\"Raw Input8\", fontsize=15)\n",
    "plt.subplot(153)\n",
    "plt.imshow(sliced_output_batch1)\n",
    "plt.title(\"Client1, Filter 0\", fontsize=15)\n",
    "plt.subplot(154)\n",
    "sliced_output_batch2 = output_batch2[0][23].detach().numpy()\n",
    "plt.imshow(sliced_output_batch2)\n",
    "plt.title(\"Client2, Filter 23\", fontsize=15)\n",
    "plt.subplot(152)\n",
    "output_batch_matched = dumm_conv_block_matched(trial_example)\n",
    "output_batch_matched = output_batch_matched[0][0].detach().numpy()\n",
    "plt.imshow(output_batch_matched)\n",
    "#plt.title(\"Client1, Filter 0\", fontsize=15)\n",
    "plt.title(\"FedMA filter0\", fontsize=15)\n",
    "plt.subplot(155)\n",
    "output_batch_avg = dumm_conv_block_avg(trial_example)\n",
    "output_batch_avg = output_batch_avg[0][0].detach().numpy()\n",
    "plt.imshow(output_batch_avg)\n",
    "plt.title(\"FedAvg, Filter 0\", fontsize=15)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
